goog.provide('dkpoints.main');

goog.require('goog.History');
goog.require('soy');

goog.require('dkpoints.menu');
goog.require('dkpoints.standings');
goog.require('dkpoints.auth');
goog.require('dkpoints.errors');
goog.require('dkpoints.admin');
goog.require('dkpoints.labs');
goog.require('dkpoints.tests');

dkpoints.baseURL = "";

dkpoints.main.main = function()
{
  var me = dkpoints.main;

  var url = window.location.href;
  dkpoints.baseURL = url.substr(0, url.indexOf("/#"));

  var iframe = /** @type {HTMLIFrameElement} */ (goog.dom.$('historyFrame'));
  var input = /** @type {HTMLInputElement} */ (goog.dom.$('historyInput'));
  
  me.firstPass = false;
  var h = new goog.History(false, "/scripts/blank.html", input, iframe);
  goog.events.listen(h, goog.History.EventType.NAVIGATE, me.loadPlace);
  h.setEnabled(true);
  
  dkpoints.menu.init();
  dkpoints.auth.init();
};

// The main navigation dispatch method.
dkpoints.main.loadPlace = function(event)
{  
  var me = dkpoints.main;
  dkpoints.referer = dkpoints.currPage || "";
  dkpoints.currPage = location.hash.substr(1); // Ignore the hash symbol.
  
  if(! dkpoints.auth.authStatus) {
    dkpoints.auth.init();
  }
  
  // The default page is the Standings page
  if(event.token == "" || event.token.match(/^[#|\/|\/|#\/|\/standings]$/))
  {
    // If the currently loaded view is not the Standings page, unload it.
    if(me.currentPackage && me.currentPackage.name != "/standings")
    {
      if(me.currentPackage.teardown) {
        me.currentPackage.teardown();
      }
      else {
        me.teardownCurrent();
      }
    }
    
    // Load the Standings page if not already loaded.
    if(me.currentPackage != dkpoints.standings) {
      me.currentPackage = dkpoints.standings;
      me.currentPackage.loadUI();
    }
  }
  
  // Authorization module
  else if(event.token.match(/^\/auth\/(.*)$/))
  {
    var mode = /^\/auth\/(.*)$/.exec(event.token)[1];
    dkpoints.auth.loadUI(dkpoints.referer, mode);
  }
  
  // Administrator Module.
  else if(event.token.match(/^\/admin\/?.*/)) {
    // Ask the admin handler what the new place is.
    var newPackage = dkpoints.admin.getPackage(event.token);
    
    // If the new package and the old package aren't the same,
    // tear down the old package and loadUI on the new one.
    if(me.currentPackage && (me.currentPackage !== newPackage)) {
      if(me.currentPackage.teardown) {
        me.currentPackage.teardown();
      }
      else {
        me.teardownCurrent();
      }
      
      // Set the new currentPackage.
      me.currentPackage = newPackage;
    }
    else if(! me.currentPackage || me.currentPackage != newPackage) {
      // If currentPackage isn't set yet, set it.
      me.currentPackage = newPackage;
    }
    
    dkpoints.admin.loadUI(me.currentPackage, event.token);
  }
  
  // Labs.
  else if(event.token.match(/^\/labs\/?/)) {
    // If the currently loaded view is not the Standings page, unload it.
    if(me.currentPackage && me.currentPackage.name != "Labs")
    {
      if(me.currentPackage.teardown) {
        me.currentPackage.teardown();
      }
      else {
        me.teardownCurrent();
      }
    }
    
    me.currentPackage = dkpoints.labs;
    dkpoints.labs.sayHi();
  }
  
  // Run tests.
  else if(event.token.match(/^\/tests\/?/)) {
    if(me.currentPackage && me.currentPackage.name != "Tests")
    {
      if(me.currentPackage.teardown) {
        me.currentPackage.teardown();
      }
      else {
        me.teardownCurrent();
      }
    }
    
    dkpoints.tests.init();
  }
  
  // Not Yet Implemented.
  else {
    if(me.currentPackage) {
      if(me.currentPackage.teardown) {
        me.currentPackage.teardown();
      }
      else {
        me.teardownCurrent();
      }
    }
    
    me.currentPackage = dkpoints.errors;
    dkpoints.errors.http404();
  }
};

dkpoints.main.teardownCurrent = function() {
  var me = dkpoints.main;
  
  // If something is showing, remove it.  Whatever was clicked wasn't built yet.
  if(me.currentPackage) {
    if(me.currentPackage.tearDown) {
      me.currentPackage.tearDown();
    }
    else {
      if(goog.dom.$('body_content').lastChild) {
        me.genericTeardown( /** @type {!Node} */ (goog.dom.$('body_content').lastChild), 0);
      }
    }
    
    delete me.currentPackage;
  }
}

/**
 * Recursive teardown of DOM structure
 * @param {!Node} topElement The element to dive into and start removing children
 * @param {number} animDelay The setTimeout interval.
 */
dkpoints.main.genericTeardown = function(topElement, animDelay) {
  var toRemove = dkpoints.main.findLastChild(topElement);

  // At the end of the removal, toRemove will already be disconnected
  if(toRemove.parentNode) {
    toRemove.parentNode.removeChild(toRemove);
  }
  
  if(topElement) {
    setTimeout(dkpoints.main.removeLast(topElement, animDelay), animDelay);
  }
}

/**
 * Recursively finds the last child of the given DOM element
 * @param {!Node} topEl The element whose child we're trying to find.
 * @return {!Node} The last child of the given element.
 */
dkpoints.main.findLastChild = function(topEl) {
  if(topEl.lastChild){
    if(topEl.lastChild.lastChild) {
      return dkpoints.main.findLastChild(topEl.lastChild);
    }
    else {
      return topEl.lastChild;
    }
  }
  else {
    return topEl;
  }
}

/**
 * Generates closure for recursive teardown of DOM structure
 * @param {!Node} toRemove The element to dive into and start removing children
 * @param {number} animDelay The setTimeout interval.
 */
dkpoints.main.removeLast = function(toRemove, animDelay) {
  return (function() {
    dkpoints.main.genericTeardown(toRemove, animDelay);
  });
}

// Run the thing!
dkpoints.main.main();